package com.coincalf.service;

import com.baomidou.mybatisplus.plugins.Page;
import com.coincalf.dto.ForexAssetDTO;
import com.coincalf.dto.ResultDTO;
import com.coincalf.dto.SymbolAssetDTO;
import com.coincalf.entity.Account;
import com.baomidou.mybatisplus.service.IService;
import com.coincalf.entity.User;
import com.coincalf.framework.dto.ApplyWithdrawDTO;
import com.coincalf.framework.enums.BusinessType;
import com.coincalf.framework.exception.AccountException;
import com.coincalf.framework.exception.GlobalDefaultException;
import com.coincalf.framework.http.Response;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;

/**
 * <p>
 * 用户财产记录 服务类
 * </p>
 *
 * @author qiang
 * @since 2018-05-12
 */
public interface AccountService extends IService<Account> {

    /**
     * 根据用户ID和币种名称查询资金账户
     *
     * @param userId   用户ID
     * @param coinName 币种名称
     * @return
     */
    Account selectByUserAndCoinName(long userId, String coinName);

    /**
     * 根据用户ID和币种名称查询资金账户
     *
     * @param userId 用户ID
     * @param coinId 币种ID
     * @return
     */
    Account queryByUserIdAndCoinId(long userId, long coinId);

    /**
     * 冻结资金
     *
     * @param userId       用户ID
     * @param coinId       币种ID
     * @param amount       冻结金额
     * @param businessType 业务类型
     * @param orderId      关联订单号
     * @return
     */
    boolean lockAmount(
            long userId,
            long coinId,
            BigDecimal amount,
            BusinessType businessType,
            long orderId
    ) throws AccountException;

    /**
     * 解冻资金
     *
     * @param userId       用户ID
     * @param coinId       币种ID
     * @param amount       冻结金额
     * @param businessType 业务类型
     * @param orderId      关联订单号
     * @return
     */
    boolean unlockAmount(
            long userId,
            long coinId,
            BigDecimal amount,
            BusinessType businessType,
            long orderId
    ) throws AccountException;

    /**
     * 解冻资金
     *
     * @param userId       用户ID
     * @param coinId       币种ID
     * @param amount       冻结金额
     * @param businessType 业务类型
     * @param remark       备注
     * @param orderId      关联订单号
     * @return
     */
    boolean addAmount(
            long userId,
            long coinId,
            BigDecimal amount,
            BusinessType businessType,
            String remark,
            long orderId
    ) throws AccountException;


    /**
     * 根据用户名称和币种名称查询资金账户
     *
     * @param coinId   币种ID
     * @param userName 用户名称
     * @return
     */
    Page<Account> selectAccountByNames(Page<Account> page, long coinId, String userName, long agencyUserId, String createTime, long parentId);

    /**
     * 代理商-查询当前用户下所有代理列表
     *
     * @param agencyUserId
     * @return
     */
    List<Map<String, Object>> selectAllLevelUser(long agencyUserId);

    /**
     * 代理商-账户资产统计
     *
     * @param anencyUserId
     * @return
     */
    ResultDTO selectAccountTotal(long anencyUserId);

    /**
     * 统计账户资产
     *
     * @param userId
     * @return
     */
    Map<String, Object> countAssets(Long userId) throws ExecutionException;

    /**
     * 查询统计实时资金账户
     *
     * @param userId 用户ID
     * @param coinId 币种ID
     * @return
     */
    ForexAssetDTO forexAsset(long userId, long coinId) throws GlobalDefaultException;

    /**
     * 币币交易用户交易对账户资产
     *
     * @param symbol 交易对标识符
     * @param userId 用户ID
     */
    SymbolAssetDTO queryAccount(String symbol, long userId);

    /**
     * 获取钱包充值地址
     *
     * @param coinId 币种ID
     * @param userId 用户ID
     * @return
     */
    Map<String, String> queryRechargeAddress(Long coinId, Long userId);

    /**
     * 申请提币
     *
     * @param applyWithdraw 申请提币参数
     * @param user          用户
     */
    Response applyWithdraw(ApplyWithdrawDTO applyWithdraw, User user);

    /**
     * 注册同步币种账户和外汇账户
     */
    boolean syncAccount(Long userId);

    /**
     * 资金转移
     *
     * @param fromUserId   转出账户
     * @param toUserId     转入账户
     * @param coinId       币种
     * @param amount       金额
     * @param businessType 业务类型
     * @param orderId      关联订单号
     */
    boolean transferAmount(Long fromUserId, Long toUserId, Long coinId, BigDecimal amount, BusinessType businessType, Long orderId);

    int addAmountById(Long accountId, BigDecimal amount);

    int subAmountById(Long accountId, BigDecimal amount);
}
